<?php

namespace app\admin\validate\crm;

use app\common\model\CrmFieldConfigs;
use app\common\model\CrmFieldGroups;
use think\Validate;

class CrmSettingValidate extends Validate
{
    protected $scene = ['save'];


    public function check($data, $rules = [], $batch = false):bool
    {
        $groupRules = [
            'id'   => 'integer|egt:0',
            'name' => 'require|length:2,60',
            'code' => 'require|length:2,30|alphaDash|checkGroupCodeUnique:code',
            'sort' => 'integer|egt:0',
        ];
        $groupMsg  = [
            'id.integer'   => '分组ID必须是整数',
            'id.egt'       => '分组ID必须≥0',
            'name.require' => '分组名称必填',
            'name.length'     => '分组名称不超过60个字符',
            'code.require' => '分组编码必填',
            'code.length'     => '分组编码不超过30个字符',
            'code.alphaDash'=> '分组编码只能是字母、数字、下划线',
            'sort.integer' => '排序必须是整数',
            'sort.egt'     => '排序必须≥0',
        ];

        $vGroup = new Validate;
        $vGroup->rule($groupRules)->message($groupMsg);
        $vGroup->extend('checkGroupCodeUnique', [$this, 'checkGroupCodeUnique']);

        $fieldRules = [
            'id'        => 'integer|egt:0',
            'group_id'  => 'integer|egt:0',
            'name'      => 'require|length:2,60|alphaDash|checkFieldNameUnique',
            'label'     => 'require|length:2,60',
            'type'      => 'require|in:text,textarea,number,select,checkbox,radio,date,datetime,image,images,region',
            'required'  => 'in:0,1',
            'sort'      => 'integer|egt:0',
            'validation'=> 'length:0,255',
            'options'   => 'checkOptionsFormat',
        ];
        $fieldMsg = [
            'id.integer'      => '字段ID必须是整数',
            'id.egt'          => '字段ID必须≥0',
            'group_id.integer'=> '字段所属分组ID必须是整数',
            'name.require'    => '字段名称必填',
            'name.length'        => '字段名称不超过60个字符',
            'name.alphaDash'  => '字段名称只能是字母、数字、下划线',
            'label.require'   => '字段标签必填',
            'label.length'       => '字段标签不超过60个字符',
            'type.require'    => '字段类型必填',
            'required.in'     => '是否必填只能是0或1',
            'sort.integer'    => '排序必须是整数',
            'validation.max'  => '验证规则不超过255个字符',
            'options.array'   => '选项必须是数组',
        ];

        $vField = new Validate;
        $vField->rule($fieldRules)->message($fieldMsg);
        $vField->extend('checkFieldNameUnique', [$this, 'checkFieldNameUnique']);
        $vField->extend('checkOptionsFormat', [$this, 'checkOptionsFormat']);

        foreach ($data as $idx => $group) {
            if (!$vGroup->check($group)) {
                $this->error = "分组[{$group['name']}]：" . $vGroup->getError();
                return false;
            }

            if (!empty($group['fields']) && is_array($group['fields'])) {
                foreach ($group['fields'] as $fIdx => $field) {
                    if (!$vField->check($field)) {
                        $this->error = "分组「{$group['name']}」的字段「{$field['name']}」：" . $vField->getError();
                        return false;
                    }
                }
            }
        }

        return true;
    }

    protected function checkGroupCodeUnique($value, $rule, $data = [])
    {
        $id = $data['id'] ?? 0;
        return CrmFieldGroups::where('code', $value)
            ->when($id > 0, fn($q) => $q->where('id', '<>', $id))
            ->value('id') ? '分组编码已存在' : true;
    }

    protected function checkFieldNameUnique($value, $rule, $data = [])
    {
        $id = $data['id'] ?? 0;
        return CrmFieldConfigs::where('name', $value)
            ->when($id > 0, fn($q) => $q->where('id', '<>', $id))
            ->value('id') ? '字段名称已存在' : true;
    }

    protected function checkOptionsFormat($value, $rule, $data = [])
    {
        $type = $data['type'] ?? '';
        if (!in_array($type, ['select', 'multi_select', 'radio', 'checkbox'])) {
            return true;
        }
        if (is_string($value)) {
            $value = json_decode($value, true);
        }
        if (!is_array($value) || empty($value)) {
            return '该字段类型必须提供选项数据';
        }
        foreach ($value as $opt) {
            if (!is_array($opt) || !isset($opt['value'], $opt['label'])) {
                return '选项格式不正确，必须包含value和label字段';
            }
        }
        return true;
    }

    /**
     * 获取错误信息
     * @param bool  $withKey 是否包含字段信息
     * @return array|string
     */
    public function getError(bool $withKey = false)
    {
        if (is_string($this->error)) {
            return $this->error;
        }

        if (is_array($this->error) && count($this->error) > 0) {
            return current($this->error);
        }

        return '';
    }
}